package cn.iocoder.yudao.module.system.controller.admin.auth;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO;
import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.infra.service.config.ConfigService;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
import cn.iocoder.yudao.module.system.service.permission.MenuService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.social.SocialClientService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Tag(name = "管理后台 - 认证")
@RestController
@RequestMapping("/system/auth")
@Validated
@Slf4j
public class AuthController {

    @Resource
    private AdminAuthService authService;
    @Resource
    private AdminUserService userService;
    @Resource
    private RoleService roleService;
    @Resource
    private MenuService menuService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private SocialClientService socialClientService;
    @Resource
    private ConfigService configService;
    @Resource
    private SecurityProperties securityProperties;

    @PostMapping("/login")
    @PermitAll
    @Operation(summary = "使用账号密码登录")
    public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
        return success(authService.login(reqVO));
    }



    /*
    *SSO登录
    * 首先获取Token(URL：https://oa-test-sso.fmc-asia.cn/api/token)
    * https://sso.fmc-asia.cn/api/token
    * 然后附带Token发送请求，获取到用户code，在系统中进行查找，查找到用户后设置用户信息
    * 最后带着用户信息进行跳转
    */
    @PostMapping("/fkc_sso/authorize")
    @PermitAll
    @Operation(summary = "SSO单点登录")
    public CommonResult<AuthLoginRespVO> loginOfSSO(@RequestBody @Valid String datastr) {
        log.info(datastr);
        JSONObject jsonObject = JSON.parseObject(datastr);
        log.info("SSO单点登录获取URL参数:",jsonObject);
        String token = String.valueOf(jsonObject.get("token"));
        log.info("token参数:",token);
        /*从后台获取配置*/
        ConfigDO config = configService.getConfigByKey("SSOToken");
        if (config == null) {
            log.error("SSOURL未配置！！！");
        }
        /*获取SSOURL*/
        String ssourl = config.getValue();
        /*获取用户NO*/
        log.info(config.getValue());
        String userNo = getUserNoByToken(ssourl,token);
        log.info("登录用户NO：",userNo);
        AuthLoginRespVO userinfo = null;
        /*获取用户信息并设置登录信息*/
        if (userNo==null){
            log.error("获取用户信息失败，userNo未空");
        }else{
            userinfo = authService.loginbycode(userNo);
        }
        return success(userinfo);
    }

    /*
     *根据Token和url获取用户编码
     *  */
    public String getUserNoByToken(String url,String token) {
        //String url = "https://oa-test-sso.fmc-asia.cn/api/token";
        //String token = "Z4JksjhUx/2QUOZc0noUNSerX6iLmuV+cK2NzbKgQ4lwRw03L3qiHYKoPPKgfGIpqrqqhj/AMus0LziBbsMFPls/7D6KD/47/DoX+zMmt1KcbaygfGcJIODlgPSh0l9+Nl6sdHEcJwmTopy/lXrD0+BgzjUDhKSi3nqSPTQSi1M=";
        String returnCode = "";
        String userNo = null;
        CloseableHttpClient httpClient = null;
        log.info("=================================通过URL和Token获取用户信息Start================================");
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            Map<String, Object> param = new HashMap<>();
            param.put("Token", token);
            String entrtyJson = JSON.toJSONString(param);
            StringEntity strEntity = new StringEntity(entrtyJson, "UTF-8");
            strEntity.setContentEncoding("UTF-8");
            strEntity.setContentType("application/json");
            httpPost.setEntity((HttpEntity)strEntity);
            httpPost.addHeader("token", token);
            System.out.println("Executing request " + httpPost.getRequestLine());
            CloseableHttpResponse responseBody = httpClient.execute((HttpUriRequest)httpPost);
            log.info("获取请求返回值",responseBody);
            HttpEntity entity = responseBody.getEntity();
            String resStr = EntityUtils.toString(entity);
            JSONObject object = JSONObject.parseObject(resStr);
            log.info("获取返回token用户信息",object);
            returnCode = object.getString("Code");
            System.out.println(object);

            if (StringUtils.isNotBlank(returnCode) && returnCode!=null && StringUtils.equals(returnCode, "1")) {
                userNo = object.getString("No");
            } else {
                throw exception(ErrorCodeConstants.GETUSERNO_BY_URL_TOKEN);
            }
            log.info("=================================END================================");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (httpClient != null)
                    httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return userNo;
    }

    @PostMapping("/logout")
    @PermitAll
    @Operation(summary = "登出系统")
    public CommonResult<Boolean> logout(HttpServletRequest request) {
        String token = SecurityFrameworkUtils.obtainAuthorization(request,
                securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
        if (StrUtil.isNotBlank(token)) {
            authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
        }
        return success(true);
    }

    @PostMapping("/refresh-token")
    @PermitAll
    @Operation(summary = "刷新令牌")
    @Parameter(name = "refreshToken", description = "刷新令牌", required = true)
    public CommonResult<AuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
        return success(authService.refreshToken(refreshToken));
    }

    @GetMapping("/get-permission-info")
    @PermitAll
    @Operation(summary = "获取登录用户的权限信息")
    public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
        System.out.println("=======================================进入获取用户权限");
        // 1.1 获得用户信息
        AdminUserDO user = userService.getUser(getLoginUserId());
        if (user == null) {
            return success(null);
        }

        // 1.2 获得角色列表
        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
        if (CollUtil.isEmpty(roleIds)) {
            return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
        }
        List<RoleDO> roles = roleService.getRoleList(roleIds);
        roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色

        // 1.3 获得菜单列表
        Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
        List<MenuDO> menuList = menuService.getMenuList(menuIds);
        menuList = menuService.filterDisableMenus(menuList);

        // 2. 拼接结果返回
        return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
    }

    // ========== 短信登录相关 ==========

    @PostMapping("/sms-login")
    @PermitAll
    @Operation(summary = "使用短信验证码登录")
    public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
        return success(authService.smsLogin(reqVO));
    }

    @PostMapping("/send-sms-code")
    @PermitAll
    @Operation(summary = "发送手机验证码")
    public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
        authService.sendSmsCode(reqVO);
        return success(true);
    }

    // ========== 社交登录相关 ==========

    @GetMapping("/social-auth-redirect")
    @PermitAll
    @Operation(summary = "社交授权的跳转")
    @Parameters({
            @Parameter(name = "type", description = "社交类型", required = true),
            @Parameter(name = "redirectUri", description = "回调路径")
    })
    public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
                                            @RequestParam("redirectUri") String redirectUri) {
        return success(socialClientService.getAuthorizeUrl(
                type, UserTypeEnum.ADMIN.getValue(), redirectUri));
    }

    @PostMapping("/social-login")
    @PermitAll
    @Operation(summary = "社交快捷登录，使用 code 授权码", description = "适合未登录的用户，但是社交账号已绑定用户")
    public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
        return success(authService.socialLogin(reqVO));
    }



    public String getUrl (String base64String) {
        // 假设这是你的Base64编码的字符串
        /*String base64String = "eyJkYiI6ICJvZG9vbmJkIn0=";*/

        // 解码Base64字符串
        byte[] decodedBytes = Base64.getDecoder().decode(base64String);

        // 将解码后的字节序列转换为字符串
        String jsonString = new String(decodedBytes);

        // 使用Jackson解析JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 将字符串解析为JsonNode对象
            JsonNode jsonNode = objectMapper.readTree(jsonString);

            // 打印解析后的JSON对象
            System.out.println(jsonNode.toPrettyString());

            // 根据需要操作jsonNode对象
            // 例如，获取某个字段的值
            String someValue = jsonNode.get("RedirectUrl").asText();
            System.out.println("Value of 'someKey': " + someValue);
            return someValue;

        } catch (Exception e) {
            e.printStackTrace();
            return  e.getMessage();
        }
    }

}
